﻿using System;
using System.Data.Services.Design;
using System.Xml;
using System.IO;
using System.Reflection;
using Niagara.Core;
using System.Data.Services.Client;
using System.Net;
using System.Threading;
using System.Globalization;

namespace NiagaraDataServiceUtil
{
  class Program
  {
    static int Main(string[] args)
    {

      Thread.CurrentThread.CurrentUICulture = CultureInfo.CurrentUICulture.GetConsoleFallbackUICulture();
      int codePage = Console.OutputEncoding.CodePage;
      if (((codePage != 0xfde9) && (codePage != Thread.CurrentThread.CurrentUICulture.TextInfo.OEMCodePage)) && (codePage != Thread.CurrentThread.CurrentUICulture.TextInfo.ANSICodePage))
      {
        Thread.CurrentThread.CurrentUICulture = new CultureInfo("en");
      }


      GeneratorCommandLine cmd = new GeneratorCommandLine();
      if (!cmd.ParseAndContinue(args))
      {
        return -1;
      }

      Console.WriteLine(cmd.GetLogo());

      var serviceUri = new DataServiceContext(new Uri(cmd.DSAddress, UriKind.RelativeOrAbsolute)).GetMetadataUri();

      XmlReaderSettings settings = new XmlReaderSettings();
      XmlResolver resolver = new XmlUrlResolver();
      resolver.Credentials = CredentialCache.DefaultNetworkCredentials;
      settings.XmlResolver = resolver;

      XmlReader results = null;
      try
      {
        var req = (HttpWebRequest)WebRequest.Create(serviceUri);
        var res = req.GetResponse();
        if (res.ResponseUri != serviceUri)
        {
          Console.WriteLine("Failed to retrieve the metadata for the service.  Most likely the service is secured");
          return -1;
        }
        results = XmlReader.Create(res.GetResponseStream(), settings);
      }
      catch (Exception ex)
      {
        Console.WriteLine("Failed to retrieve the metadata for the service: {0}", ex.Message);
        return -1;
      }

      Assembly metadataAssembly = null;
      try
      {
        string fullPath = Path.GetFullPath(cmd.EntityAssembly);
        metadataAssembly = Assembly.LoadFile(fullPath);
      }
      catch (Exception ex)
      {
        Console.WriteLine("Failed to find the Entity Assembly: {0}", ex.Message);
        return -1;
      }

      try
      {
        using (var writer = new StreamWriter(cmd.OutputPath))
        {
          var generator = new ValidationDataServiceProxyGenerator(results,
            writer,
            cmd.Namespace,
            new ReflectionAttributeMetadataProvider(metadataAssembly))
          {
            DataServiceVersion = cmd.Version == "V1" ? DataServiceCodeVersion.V1 : DataServiceCodeVersion.V2,
            Language = cmd.Language == "CS" ? LanguageOption.GenerateCSharpCode : LanguageOption.GenerateVBCode,
            UseDataServiceCollection = cmd.GenerateBindingCode,
            GenerateValidation = cmd.GenerateValidationCode
          };

          var errors = generator.GenerateCode();

          foreach (var error in errors) Console.WriteLine(error.Message);

          if (errors.Count > 0)
          {
            Console.WriteLine(string.Format("{0} errors occurred during code generation.", errors.Count));
            return -1;
          }

          Console.WriteLine("Generation Complete...");
          return 0;
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine("Exception Thrown during code genereration:");
        Console.WriteLine(ex.Message);
#if DEBUG
        Console.WriteLine();
        Console.WriteLine(ex.ToString());
#endif
        return -1;
      }
      finally
      {
        ((IDisposable)results).Dispose();
      }

    }
  }
}
